﻿using System.Runtime.CompilerServices;


namespace KinonekoSoftware.CodariaDB.Runtimes
{
    partial class RepositoryRuntime
    {

        #region RepositoryManagerBuilder

        class RepositoryRuntimeBuilder : IRepositoryRuntimeBuilder
        {
            private readonly HashSet<Type>              _dictionary;
            private readonly List<Engine>               _engines;
            private readonly List<object>               _initializers;
            private readonly Dictionary<string, Engine> _dataSetMap;
            private readonly ILogger                    _logger;
            private readonly object                     _sync;


            public RepositoryRuntimeBuilder(ILogger logger)
            {
                _dictionary   = new HashSet<Type>();
                _dataSetMap   = new Dictionary<string, Engine>();
                _engines      = new List<Engine>(16);
                _initializers = new List<object>(16);
                _sync         = new object();
                _logger       = logger;
            }


            /// <summary>
            /// 注册数据引擎。
            /// </summary>
            /// <typeparam name="TDataSet">指定的引擎类型。</typeparam>
            /// <returns>返回一个<see cref="IRepositoryRuntimeBuilder"/></returns>
            public IRepositoryRuntimeBuilder Setup<TDataSet>() where TDataSet : Engine
            {
                var key = typeof(TDataSet);
                lock (_sync)
                {
                    if (_dictionary.Contains(key))
                    {
                        return this;
                    }

                    var engine = ClassStatic.CreateInstance<TDataSet>();

                    if (engine is null)
                        return this;

                    _engines.Add(engine);
                    _dataSetMap.TryAdd(engine.EngineID, engine);
                    _dictionary.Add(key);
                }

                return this;
            }

            /// <summary>
            /// 注册数据引擎。
            /// </summary>
            /// <param name="engine">是否为懒加载模式</param>
            /// <returns>返回一个<see cref="IRepositoryRuntimeBuilder"/></returns>
            public IRepositoryRuntimeBuilder Setup(Engine engine)
            {
                if (engine is null)
                {
                    return this;
                }
                
                var key = engine.GetType();
                
                lock (_sync)
                {
                    if (_dictionary.Contains(key))
                    {
                        return this;
                    }
                    
                    _engines.Add(engine);
                    _dataSetMap.TryAdd(engine.EngineID, engine);
                    _dictionary.Add(key);
                }

                return this;
            }


            /// <summary>
            /// 注册数据引擎。
            /// </summary>
            /// <param name="initializer">指定的引擎类型。</param>
            /// <returns>返回一个<see cref="IRepositoryRuntimeBuilder"/></returns>
            public IRepositoryRuntimeBuilder Initialize(IRepositoryInitializer initializer) 
            {
                if (initializer is null)
                {
                    return this;
                }
                
                var key = initializer.GetType();
                lock (_sync)
                {
                    if (_dictionary.Contains(key))
                    {
                        return this;
                    }
                    _initializers.Add(initializer);
                    _dictionary.Add(key);
                }

                return this;
            }

            /// <summary>
            /// 注册数据引擎。
            /// </summary>
            /// <param name="maintainer">指定的引擎类型。</param>
            /// <returns>返回一个<see cref="IRepositoryRuntimeBuilder"/></returns>
            public IRepositoryRuntimeBuilder Maintain(IRepositoryMaintainer maintainer)
            {
                if (maintainer is null)
                {
                    return this;
                }
                var key = maintainer.GetType();
                
                lock (_sync)
                {
                    if (_dictionary.Contains(key))
                    {
                        return this;
                    }

                    _initializers.Add(maintainer);
                    _dictionary.Add(key);
                }

                return this;
            }

            /// <summary>
            /// 构建引擎。
            /// </summary>
            /// <returns>返回一个<see cref="RepositoryRuntime"/></returns>
            public RepositoryRuntime Build()
            {
                lock (_sync)
                {
                    return new RepositoryRuntime(
                                                 _logger,
                                                 _engines,
                                                 _initializers,
                                                 _dataSetMap);
                }
            }



        }

        #endregion

        /// <summary>
        /// 创建构建器。
        /// </summary>
        /// <returns>返回一个新的构建器实例。</returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static IRepositoryRuntimeBuilder CreateBuilder(ILogger logger)
        {
            return new RepositoryRuntimeBuilder(logger);
        }

        /// <summary>
        /// 创建默认数据库管理器。
        /// </summary>
        /// <returns>返回一个新的数据库管理器实例。</returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static RepositoryRuntime GetDefaultRuntime(ILogger logger)
        {
            return CreateBuilder(logger)
                   //
                   // Important
                   //
                  .Setup(new ConceptSystem())
                  .Setup(new RemoteSystem())
                  .Setup(new VariantsSystem())
                  .Setup(new GravatarSystem())
                  .Setup(new ImageSystem())
                  .Setup(new MusicSystem())
                  .Setup(new IconSystem())
                  .Setup(new EmojiSystem())
                  .Setup(new UsageSystem())
                  .Setup(new TimeSystem())
                   
                   //
                   //
                   //
                  .Setup(new InstanceEngine())
                  .Setup(new InstanceCacheEngine())
                  .Setup(new TeamCacheEngine())
                   //
                   //
                   //
                  .Setup(new TemplateEngine())
                  .Setup(new TemplatedContentEngine())
                  .Setup(new PartEngine())
                  .Setup(new ImpressionEngine())
                  .Setup(new RelationEngine())
                  .Setup(new KeywordEngine())
                  .Setup(new CompositeEngine())
                   
                   //
                   //
                   //
                  .Setup(new NotionEngine())
                  .Setup(new ForumEngine())
                  .Setup(new TalkingEngine())
                   
                   //
                   //
                   //
                  .Setup(new TheoryEngine_Element())
                  .Setup(new TheoryEngine_Rarity())
                  .Setup(new TheoryEngine_Vocabulary())
                  .Setup(new TheoryEngine_Chikara())
                   
                   //
                   //
                   //
                  // .Maintain(new UpdateTo100())
                  // .Maintain(new UpdateTo110())
                  /* .Maintain(new UpdateTo200()) */
                  .Build();
        }
    }
}